<template>
  <div class="tiptap-editor">
    <!-- 工具栏 -->
    <div v-if="editor" class="editor-toolbar">
      <!-- 文本格式 -->
      <el-button-group>
        <el-button
          :class="{ 'is-active': editor.isActive('bold') }"
          size="small"
          @click="editor.chain().focus().toggleBold().run()"
        >
          <i class="el-icon-s-opportunity" />
        </el-button>
        <el-button
          :class="{ 'is-active': editor.isActive('italic') }"
          size="small"
          @click="editor.chain().focus().toggleItalic().run()"
        >
          <i>I</i>
        </el-button>
        <el-button
          :class="{ 'is-active': editor.isActive('underline') }"
          size="small"
          @click="editor.chain().focus().toggleUnderline().run()"
        >
          <u>U</u>
        </el-button>
      </el-button-group>

      <!-- 标题 -->
      <el-dropdown style="margin-left: 10px;" @command="setHeading">
        <el-button size="small">
          标题<i class="el-icon-arrow-down el-icon--right" />
        </el-button>
        <el-dropdown-menu slot="dropdown">
          <el-dropdown-item command="p">正文</el-dropdown-item>
          <el-dropdown-item command="h1">标题 1</el-dropdown-item>
          <el-dropdown-item command="h2">标题 2</el-dropdown-item>
          <el-dropdown-item command="h3">标题 3</el-dropdown-item>
        </el-dropdown-menu>
      </el-dropdown>

      <!-- 列表 -->
      <el-button-group style="margin-left: 10px;">
        <el-button
          :class="{ 'is-active': editor.isActive('bulletList') }"
          size="small"
          @click="editor.chain().focus().toggleBulletList().run()"
        >
          <i class="el-icon-s-unfold" />
        </el-button>
        <el-button
          :class="{ 'is-active': editor.isActive('orderedList') }"
          size="small"
          @click="editor.chain().focus().toggleOrderedList().run()"
        >
          <i class="el-icon-s-operation" />
        </el-button>
      </el-button-group>

      <!-- 插入图片 -->
      <el-button
        size="small"
        style="margin-left: 10px;"
        @click="showImageDialog = true"
      >
        <i class="el-icon-picture" /> 图片
      </el-button>

      <!-- 插入视频 -->
      <el-button
        size="small"
        @click="showVideoDialog = true"
      >
        <i class="el-icon-video-camera" /> 视频
      </el-button>

      <!-- 清除格式 -->
      <el-button
        size="small"
        style="margin-left: 10px;"
        @click="editor.chain().focus().clearNodes().unsetAllMarks().run()"
      >
        <i class="el-icon-brush" /> 清除格式
      </el-button>

      <!-- 显示源码 -->
      <el-button
        :class="{ 'is-active': showSourceCode }"
        size="small"
        @click="toggleSourceCode"
      >
        <i class="el-icon-view" /> 源码
      </el-button>
    </div>

    <!-- 编辑器内容区 -->
    <div
      class="editor-content"
      @paste="handlePaste"
      @drop="handleDrop"
      @dragover.prevent="handleDragOver"
      @dragenter.prevent="handleDragEnter"
      @dragleave="handleDragLeave"
    >
      <!-- 富文本编辑器 -->
      <editor-content v-show="!showSourceCode" :editor="editor" />

      <!-- 源码编辑器 -->
      <div v-show="showSourceCode" class="source-code-editor">
        <el-input
          v-model="sourceCodeContent"
          type="textarea"
          :rows="15"
          placeholder="HTML源码..."
          @input="updateFromSourceCode"
        />
      </div>

      <!-- 拖拽上传提示 -->
      <div v-if="isDragOver" class="drag-upload-overlay">
        <div class="drag-upload-content">
          <i class="el-icon-upload" />
          <p>松开鼠标上传文件</p>
          <small>支持图片、视频、文档等多种格式</small>
        </div>
      </div>

      <!-- 单个文件上传进度 -->
      <div v-if="uploading && !batchUploading" class="upload-progress">
        <el-progress :percentage="uploadProgress" />
        <span>正在上传...</span>
      </div>

      <!-- 批量上传进度 -->
      <div v-if="batchUploading" class="batch-upload-progress">
        <div class="progress-header">
          <span>批量上传中... ({{ batchUploadProgress.completed }}/{{ batchUploadProgress.total }})</span>
          <span v-if="batchUploadProgress.failed > 0" class="failed-count">失败: {{ batchUploadProgress.failed }}</span>
        </div>
        <el-progress
          :percentage="Math.round((batchUploadProgress.completed / batchUploadProgress.total) * 100)"
          :status="batchUploadProgress.failed > 0 ? 'exception' : 'success'"
        />
        <div v-if="batchUploadProgress.current" class="current-file">
          当前: {{ batchUploadProgress.current }}
        </div>
      </div>
    </div>

    <!-- 图片插入对话框 -->
    <el-dialog
      title="插入图片"
      :visible.sync="showImageDialog"
      width="500px"
    >
      <el-form :model="imageForm" label-width="80px">
        <el-form-item label="图片地址">
          <el-input v-model="imageForm.url" placeholder="请输入图片URL或上传图片" />
        </el-form-item>
        <el-form-item label="上传图片">
          <el-upload
            :http-request="customUploadImage"
            :show-file-list="false"
            accept="image/*"
          >
            <el-button size="small" type="primary">点击上传</el-button>
          </el-upload>
        </el-form-item>
        <el-form-item label="图片描述">
          <el-input v-model="imageForm.alt" placeholder="可选：图片描述文字" />
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="showImageDialog = false">取消</el-button>
        <el-button type="primary" @click="insertImage">确定</el-button>
      </span>
    </el-dialog>

    <!-- 视频插入对话框 -->
    <el-dialog
      title="插入视频"
      :visible.sync="showVideoDialog"
      width="500px"
    >
      <el-form :model="videoForm" label-width="80px">
        <el-form-item label="视频类型">
          <el-radio-group v-model="videoForm.type">
            <el-radio label="url">视频链接</el-radio>
            <el-radio label="embed">嵌入代码</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item v-if="videoForm.type === 'url'" label="视频地址">
          <el-input v-model="videoForm.url" placeholder="支持直链视频文件、YouTube、Vimeo等" />
          <div style="font-size: 12px; color: #909399; margin-top: 5px;">
            支持格式：.mp4、.webm、.ogg 等视频文件，以及 YouTube、Vimeo 嵌入视频
          </div>
        </el-form-item>
        <el-form-item v-else label="嵌入代码">
          <el-input
            v-model="videoForm.embedCode"
            type="textarea"
            :rows="4"
            placeholder="粘贴视频的嵌入代码（iframe、embed 等）"
          />
          <div style="font-size: 12px; color: #909399; margin-top: 5px;">
            支持任意 HTML 嵌入代码，如 iframe、embed 标签等
          </div>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="showVideoDialog = false">取消</el-button>
        <el-button type="primary" @click="insertVideo">确定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import { Editor, EditorContent } from '@tiptap/vue-2'
import StarterKit from '@tiptap/starter-kit'
import Image from '@tiptap/extension-image'
import Link from '@tiptap/extension-link'
import Underline from '@tiptap/extension-underline'
import Placeholder from '@tiptap/extension-placeholder'
import { Node } from '@tiptap/core'
import { getToken } from '@/utils/auth'

// 自定义视频节点扩展
const VideoExtension = Node.create({
  name: 'video',

  group: 'block',

  content: '',

  marks: '',

  atom: true,

  addAttributes() {
    return {
      src: {
        default: null
      },
      controls: {
        default: true
      },
      style: {
        default: 'width: 100%; max-width: 600px;'
      }
    }
  },

  parseHTML() {
    return [
      {
        tag: 'video'
      }
    ]
  },

  renderHTML({ HTMLAttributes }) {
    return ['video', HTMLAttributes]
  },

  addCommands() {
    return {
      setVideo: options => ({ commands }) => {
        return commands.insertContent({
          type: this.name,
          attrs: options
        })
      }
    }
  }
})

export default {
  name: 'TiptapEditor',
  components: {
    EditorContent
  },
  props: {
    value: {
      type: String,
      default: ''
    },
    placeholder: {
      type: String,
      default: '开始输入内容...'
    },
    // 文件夹标签 - 用于crm文件系统
    folderTag: {
      type: String,
      default: 'TiptapEditor'
    },
    // 目录名称
    directoryName: {
      type: String,
      default: 'TiptapEditorFiles'
    },
    // 业务阶段ID - 用于组织上传文件目录结构
    businessStageId: {
      type: [String, Number],
      default: null
    }
  },
  data() {
    return {
      editor: null,
      showImageDialog: false,
      showVideoDialog: false,
      imageForm: {
        url: '',
        alt: ''
      },
      videoForm: {
        type: 'url',
        url: '',
        embedCode: ''
      },
      // 上传相关
      isDragOver: false,
      uploading: false,
      uploadProgress: 0,
      uploadUrl: '',
      // 批量上传相关
      batchUploading: false,
      batchUploadProgress: {
        total: 0,
        completed: 0,
        failed: 0,
        current: ''
      },
      // 源码编辑
      showSourceCode: false,
      sourceCodeContent: '',
      sourceCodeUpdateTimer: null
    }
  },
  computed: {
    // 上传请求头
    headers() {
      return {
        'Authorization': getToken(),
        'PTOKEN': this.$store.getters.projectId
      }
    },

    // 上传数据
    uploadData() {
      const projectId = this.$store.getters.projectId
      const businessStageId = this.businessStageId

      // 构建目录名称：project_id/业务阶段id/原目录名
      let directoryName = this.directoryName
      if (projectId && businessStageId) {
        directoryName = `${projectId}/${businessStageId}/${this.directoryName}`
      } else if (projectId) {
        directoryName = `${projectId}/${this.directoryName}`
      }

      return {
        directory_id: -1,
        acl_type: '7',
        project_id: projectId,
        directory_name: directoryName,
        folder_tag: this.folderTag,
        business_stage_id: businessStageId
      }
    }
  },
  watch: {
    value(value) {
      const isSame = this.editor.getHTML() === value
      if (isSame) {
        return
      }
      this.editor.commands.setContent(value, false)
      // 同步更新源码内容
      if (this.showSourceCode) {
        this.sourceCodeContent = value
      }
    }
  },
  mounted() {
    // 设置上传URL
    this.uploadUrl = process.env.VUE_APP_BASE_API + '/crm/api/crmfile/'

    this.editor = new Editor({
      extensions: [
        StarterKit,
        Image,
        VideoExtension,
        Link.configure({
          openOnClick: false,
          HTMLAttributes: {
            target: '_blank',
            rel: 'noopener noreferrer'
          }
        }),
        Underline,
        Placeholder.configure({
          placeholder: this.placeholder
        })
      ],
      content: this.value,
      onUpdate: () => {
        const htmlContent = this.editor.getHTML()
        this.$emit('input', htmlContent)
        // 同步更新源码内容
        if (this.showSourceCode) {
          this.sourceCodeContent = htmlContent
        }
      }
    })
  },
  beforeDestroy() {
    this.editor.destroy()
  },
  methods: {
    // 设置标题
    setHeading(command) {
      if (command === 'p') {
        this.editor.chain().focus().setParagraph().run()
      } else {
        const level = parseInt(command.charAt(1))
        this.editor.chain().focus().toggleHeading({ level }).run()
      }
    },

    // 上传前验证
    handleBeforeUpload(file) {
      return this.isValidFile(file)
    },

    // 自定义图片上传
    async customUploadImage(option) {
      const { file } = option
      if (!this.isValidFile(file)) {
        return
      }

      try {
        // 构造上传数据
        const formData = new FormData()
        formData.append('file', file)
        Object.keys(this.uploadData).forEach(key => {
          formData.append(key, this.uploadData[key])
        })

        const response = await this.uploadFileRequest(formData)
        if (response.success) {
          this.imageForm.url = response.data.url
          this.$message.success('图片上传成功')
        } else {
          this.$message.error(response.msg || '上传失败')
        }
      } catch (error) {
        console.error('上传失败:', error)
        this.$message.error('图片上传失败')
      }
    },

    // 处理图片上传成功
    handleImageUploadSuccess(response) {
      if (response.success) {
        this.imageForm.url = response.data.url
        this.$message.success('图片上传成功')
      } else {
        this.$message.error(response.msg || '上传失败')
      }
    },

    // 插入图片
    insertImage() {
      if (this.imageForm.url) {
        this.editor
          .chain()
          .focus()
          .setImage({ src: this.imageForm.url, alt: this.imageForm.alt })
          .run()
        this.showImageDialog = false
        this.imageForm = { url: '', alt: '' }
      } else {
        this.$message.warning('请输入图片地址')
      }
    },

    // 插入视频
    insertVideo() {
      let htmlContent = ''

      if (this.videoForm.type === 'url') {
        // 解析视频URL并生成嵌入代码
        const url = this.videoForm.url
        if (url.includes('youtube.com') || url.includes('youtu.be')) {
          const videoId = this.extractYouTubeId(url)
          htmlContent = `<div class="video-wrapper embed-video"><iframe src="https://www.youtube.com/embed/${videoId}" frameborder="0" allowfullscreen></iframe></div>`
        } else if (url.includes('vimeo.com')) {
          const videoId = this.extractVimeoId(url)
          htmlContent = `<div class="video-wrapper embed-video"><iframe src="https://player.vimeo.com/video/${videoId}" frameborder="0" allowfullscreen></iframe></div>`
        } else {
          // 通用视频标签（处理直链视频文件、阿里云OSS等）
          // 使用自定义视频节点
          this.editor.chain().focus().setVideo({
            src: url,
            controls: true,
            style: 'width: 100%; max-width: 600px;'
          }).run()
          this.showVideoDialog = false
          this.videoForm = { type: 'url', url: '', embedCode: '' }
          return
        }
      } else {
        // 直接使用嵌入代码
        htmlContent = `<div class="video-wrapper">${this.videoForm.embedCode}</div>`
      }

      if (htmlContent) {
        this.editor.chain().focus().insertContent(htmlContent).run()
        this.showVideoDialog = false
        this.videoForm = { type: 'url', url: '', embedCode: '' }
      } else {
        this.$message.warning('请输入视频地址或嵌入代码')
      }
    },

    // 提取YouTube视频ID
    extractYouTubeId(url) {
      const match = url.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([^&\n?#]+)/)
      return match ? match[1] : ''
    },

    // 提取Vimeo视频ID
    extractVimeoId(url) {
      const match = url.match(/vimeo\.com\/(\d+)/)
      return match ? match[1] : ''
    },

    // 获取编辑器内容
    getContent() {
      return this.editor.getHTML()
    },

    // 获取纯文本内容
    getTextContent() {
      return this.editor.getText()
    },

    // 清空内容
    clearContent() {
      this.editor.commands.clearContent()
    },

    // 聚焦编辑器
    focus() {
      this.editor.commands.focus()
    },

    // 处理粘贴事件
    async handlePaste(event) {
      const items = (event.clipboardData || event.originalEvent.clipboardData).items
      let hasImageFile = false

      for (const item of items) {
        if (item.type.indexOf('image') === 0) {
          event.preventDefault()
          hasImageFile = true
          const blob = item.getAsFile()

          // 使用 base64 方式上传粘贴的图片
          const reader = new FileReader()
          reader.onload = (e) => {
            this.uploadBase64Image(e.target.result, item.type)
          }
          reader.readAsDataURL(blob)
          break
        }
      }

      if (!hasImageFile) {
        // 检查是否有文件
        for (const item of items) {
          if (item.kind === 'file') {
            event.preventDefault()
            const file = item.getAsFile()
            await this.uploadFile(file)
            break
          }
        }
      }
    },

    // 处理拖拽放置
    async handleDrop(event) {
      event.preventDefault()
      this.isDragOver = false

      const files = Array.from(event.dataTransfer.files)
      const validFiles = files.filter(file => this.isValidFile(file))

      if (validFiles.length === 0) {
        this.$message.warning('没有有效的文件可以上传')
        return
      }

      if (validFiles.length === 1) {
        // 单个文件使用原有逻辑
        await this.uploadFile(validFiles[0])
      } else {
        // 多个文件使用批量上传
        await this.uploadMultipleFiles(validFiles)
      }
    },

    // 处理拖拽悬停
    handleDragOver(event) {
      event.preventDefault()
      this.isDragOver = true
    },

    // 处理拖拽进入
    handleDragEnter(event) {
      event.preventDefault()
      this.isDragOver = true
    },

    // 处理拖拽离开
    handleDragLeave(event) {
      // 只有当拖拽真正离开编辑器区域时才隐藏提示
      if (!event.currentTarget.contains(event.relatedTarget)) {
        this.isDragOver = false
      }
    },

    // 验证文件类型和大小
    isValidFile(file) {
      // 支持的文件类型
      const validTypes = ['image/', 'video/', 'application/pdf', 'text/', 'application/msword', 'application/vnd.openxmlformats-officedocument']
      const isValidType = validTypes.some(type => file.type.startsWith(type))

      if (!isValidType) {
        this.$message.warning('不支持的文件类型')
        return false
      }

      // 文件大小限制 1GB
      if (file.size > 1024 * 1024 * 1024) {
        this.$message.warning('文件大小不能超过 1GB')
        return false
      }

      return true
    },

    // 上传文件（拖拽上传）
    async uploadFile(file) {
      if (!this.isValidFile(file)) {
        return
      }

      try {
        this.uploading = true
        this.uploadProgress = 0

        // 如果是视频文件，先提取封面
        if (file.type.startsWith('video/')) {
          await this.uploadVideoWithThumbnail(file)
        } else {
          // 其他文件直接上传
          await this.uploadNormalFile(file)
        }
      } catch (error) {
        console.error('上传失败:', error)
        this.$message.error('文件上传失败')
      } finally {
        this.uploading = false
        this.uploadProgress = 0
      }
    },

    // 批量上传文件
    async uploadMultipleFiles(files) {
      try {
        this.batchUploading = true
        this.batchUploadProgress = {
          total: files.length,
          completed: 0,
          failed: 0,
          current: ''
        }

        this.$message.info(`开始批量上传 ${files.length} 个文件`)

        for (let i = 0; i < files.length; i++) {
          const file = files[i]
          this.batchUploadProgress.current = file.name

          try {
            // 上传单个文件（不显示单个进度）
            const result = await this.uploadSingleFileInBatch(file)

            if (result && result.url) {
              // 依次在光标位置插入内容，避免相互覆盖
              if (result.type.startsWith('image/')) {
                this.insertImageAtEnd(result.url, result.filename)
              } else {
                this.insertFileAtEnd(result.url, result.filename, result.type)
              }
            }

            this.batchUploadProgress.completed++
          } catch (error) {
            console.error(`文件 ${file.name} 上传失败:`, error)
            this.batchUploadProgress.failed++
            this.batchUploadProgress.completed++
          }
        }

        // 上传完成提示
        const { completed, failed } = this.batchUploadProgress
        if (failed === 0) {
          this.$message.success(`批量上传完成，共上传 ${completed} 个文件`)
        } else {
          this.$message.warning(`批量上传完成，成功 ${completed - failed} 个，失败 ${failed} 个`)
        }

        // 触发批量上传完成事件
        if (completed > 0) {
          this.$emit('upload-complete', {
            type: 'batch',
            total: completed,
            failed: failed,
            success: completed - failed
          })
        }
      } catch (error) {
        console.error('批量上传失败:', error)
        this.$message.error('批量上传失败')
      } finally {
        this.batchUploading = false
        this.batchUploadProgress = {
          total: 0,
          completed: 0,
          failed: 0,
          current: ''
        }
      }
    },

    // 批量上传中的单个文件上传（简化版，不显示进度）
    async uploadSingleFileInBatch(file) {
      // 构造上传数据
      const formData = new FormData()
      formData.append('file', file)
      Object.keys(this.uploadData).forEach(key => {
        formData.append(key, this.uploadData[key])
      })

      // 使用现有的上传请求方法
      const response = await this.uploadFileRequest(formData)

      if (response && response.success) {
        return {
          url: response.data.url,
          filename: response.data.filename,
          type: response.data.content_type || file.type
        }
      } else {
        throw new Error(response?.msg || '上传失败')
      }
    },

    // 在内容末尾插入图片（用于批量上传）
    insertImageAtEnd(url, filename) {
      this.editor.chain()
        .focus()
        .setTextSelection(this.editor.state.doc.content.size)
        .setImage({
          src: url,
          alt: filename,
          title: filename
        })
        .run()
    },

    // 在内容末尾插入文件（用于批量上传）
    insertFileAtEnd(url, filename, fileType) {
      // 获取文件扩展名（处理OSS URL参数）
      const cleanFilename = this.extractFilenameFromUrl(filename)
      const fileExt = cleanFilename.split('.').pop()?.toLowerCase()

      // 根据文件类型选择emoji图标
      let emoji = '📄'
      if (['pdf'].includes(fileExt)) {
        emoji = '📄'
      } else if (['doc', 'docx'].includes(fileExt)) {
        emoji = '📝'
      } else if (['xls', 'xlsx'].includes(fileExt)) {
        emoji = '📊'
      } else if (['ppt', 'pptx'].includes(fileExt)) {
        emoji = '📈'
      } else if (['zip', 'rar', '7z', 'tar', 'gz'].includes(fileExt)) {
        emoji = '📦'
      } else if (['txt', 'md'].includes(fileExt)) {
        emoji = '📝'
      }

      this.editor.chain()
        .focus()
        .setTextSelection(this.editor.state.doc.content.size)
        .insertContent(`<p><a href="${url}" target="_blank">${emoji} ${cleanFilename}</a></p>`)
        .run()
    },

    // 上传普通文件
    async uploadNormalFile(file) {
      // 构造上传数据
      const formData = new FormData()
      formData.append('file', file)
      Object.keys(this.uploadData).forEach(key => {
        formData.append(key, this.uploadData[key])
      })

      const response = await this.uploadFileRequest(formData)

      if (response.success) {
        // 根据文件类型插入不同内容
        if (file.type.startsWith('image/')) {
          this.insertUploadedImage(response.data.url, response.data.filename)
        } else {
          this.insertUploadedFile(response.data.url, response.data.filename, file.type)
        }
        this.$message.success('文件上传成功')

        // 触发上传完成事件
        this.$emit('upload-complete', {
          type: 'single',
          file: {
            url: response.data.url,
            filename: response.data.filename,
            type: file.type
          }
        })
      } else {
        throw new Error(response.msg || '上传失败')
      }
    },

    // 上传视频并提取封面
    async uploadVideoWithThumbnail(videoFile) {
      try {
        // 第一步：提取视频封面
        const thumbnailBlob = await this.extractVideoThumbnail(videoFile)

        // 第二步：先上传封面图片
        const thumbnailFormData = new FormData()
        const thumbnailFileName = `${videoFile.name}_thumbnail.jpg`
        thumbnailFormData.append('file', thumbnailBlob, thumbnailFileName)
        Object.keys(this.uploadData).forEach(key => {
          thumbnailFormData.append(key, this.uploadData[key])
        })

        const thumbnailResponse = await this.uploadFileRequest(thumbnailFormData)

        if (!thumbnailResponse.success) {
          console.warn('封面上传失败，继续上传视频:', thumbnailResponse.msg)
        }

        // 第三步：上传视频文件，并关联封面
        const videoFormData = new FormData()
        videoFormData.append('file', videoFile)
        Object.keys(this.uploadData).forEach(key => {
          videoFormData.append(key, this.uploadData[key])
        })

        // 如果封面上传成功，添加封面URL到视频上传数据
        if (thumbnailResponse.success) {
          videoFormData.append('thumbnail_url', thumbnailResponse.data.url)
        }

        const videoResponse = await this.uploadFileRequest(videoFormData)

        if (videoResponse.success) {
          this.insertUploadedVideo(videoResponse.data.url, videoResponse.data.filename, thumbnailResponse.success ? thumbnailResponse.data.url : null)
          this.$message.success('视频上传成功')
        } else {
          throw new Error(videoResponse.msg || '视频上传失败')
        }
      } catch (error) {
        console.warn('视频封面提取失败，使用默认上传方式:', error)
        // 封面提取失败时，回退到普通上传方式
        await this.uploadNormalFile(videoFile)
      }
    },

    // 提取视频封面
    extractVideoThumbnail(videoFile) {
      return new Promise((resolve, reject) => {
        const video = document.createElement('video')
        video.crossOrigin = 'anonymous'
        video.muted = true
        video.playsInline = true

        const canvas = document.createElement('canvas')
        const ctx = canvas.getContext('2d')

        // 创建视频URL
        const videoUrl = URL.createObjectURL(videoFile)
        video.src = videoUrl

        // 设置超时，避免视频加载时间过长
        const timeout = setTimeout(() => {
          cleanup()
          reject(new Error('视频加载超时'))
        }, 10000)

        const cleanup = () => {
          URL.revokeObjectURL(videoUrl)
          clearTimeout(timeout)
        }

        video.onloadedmetadata = () => {
          // 设置canvas尺寸，限制最大尺寸避免内存问题
          const maxWidth = 800
          const maxHeight = 600
          let { videoWidth, videoHeight } = video

          if (videoWidth > maxWidth || videoHeight > maxHeight) {
            const ratio = Math.min(maxWidth / videoWidth, maxHeight / videoHeight)
            videoWidth *= ratio
            videoHeight *= ratio
          }

          canvas.width = videoWidth
          canvas.height = videoHeight

          // 跳转到第2秒（避开可能的黑屏）
          video.currentTime = Math.min(2, video.duration * 0.1)
        }

        video.onseeked = () => {
          try {
            // 绘制视频帧到canvas
            ctx.drawImage(video, 0, 0, canvas.width, canvas.height)

            // 转换为JPEG blob
            canvas.toBlob(blob => {
              cleanup()
              if (blob) {
                resolve(blob)
              } else {
                reject(new Error('无法生成视频封面'))
              }
            }, 'image/jpeg', 0.8)
          } catch (error) {
            cleanup()
            reject(error)
          }
        }

        video.onerror = (error) => {
          cleanup()
          reject(new Error('视频加载失败: ' + error.message))
        }

        // 开始加载视频
        video.load()
      })
    },

    // 上传 base64 图片（粘贴图片）
    async uploadBase64Image(base64Data, imageType = 'image/png') {
      try {
        this.uploading = true
        this.uploadProgress = 0

        const uploadData = {
          file_data: base64Data,
          directory_id: this.uploadData.directory_id,
          acl_type: this.uploadData.acl_type,
          project_id: this.uploadData.project_id,
          directory_name: this.uploadData.directory_name,
          folder_tag: this.uploadData.folder_tag,
          business_stage_id: this.uploadData.business_stage_id
        }

        const xhr = new XMLHttpRequest()
        xhr.open('POST', this.uploadUrl, true)
        xhr.setRequestHeader('Authorization', getToken())
        xhr.setRequestHeader('PTOKEN', this.$store.getters.projectId)
        xhr.setRequestHeader('Content-Type', 'application/json')

        xhr.upload.onprogress = (e) => {
          if (e.lengthComputable) {
            this.uploadProgress = Math.round((e.loaded * 100) / e.total)
          }
        }

        xhr.onload = () => {
          this.uploading = false

          if (xhr.status === 200) {
            try {
              const response = JSON.parse(xhr.responseText)
              if (response.success) {
                this.insertUploadedImage(response.data.url, response.data.filename)
                this.$message.success('图片上传成功')

                // 触发粘贴上传完成事件
                this.$emit('upload-complete', {
                  type: 'paste',
                  file: {
                    url: response.data.url,
                    filename: response.data.filename,
                    type: 'image'
                  }
                })
              } else {
                this.$message.error(`图片上传失败: ${response.msg}`)
              }
            } catch (error) {
              this.$message.error('响应解析失败')
            }
          } else {
            this.$message.error(`图片上传失败: HTTP ${xhr.status}`)
          }
        }

        xhr.onerror = () => {
          this.uploading = false
          this.$message.error('网络错误')
        }

        xhr.ontimeout = () => {
          this.uploading = false
          this.$message.error('上传超时')
        }

        xhr.timeout = 30000
        xhr.send(JSON.stringify(uploadData))
      } catch (error) {
        this.uploading = false
        console.error('上传失败:', error)
        this.$message.error('图片上传失败')
      }
    },

    // 发送上传请求
    uploadFileRequest(formData) {
      return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest()

        xhr.upload.onprogress = (e) => {
          if (e.lengthComputable) {
            this.uploadProgress = Math.round((e.loaded * 100) / e.total)
          }
        }

        xhr.open('POST', this.uploadUrl, true)
        xhr.setRequestHeader('Authorization', getToken())
        xhr.setRequestHeader('PTOKEN', this.$store.getters.projectId)

        xhr.onload = () => {
          if (xhr.status === 200) {
            try {
              const response = JSON.parse(xhr.responseText)
              resolve(response)
            } catch (error) {
              reject(new Error('响应解析失败'))
            }
          } else {
            reject(new Error(`HTTP ${xhr.status}: ${xhr.statusText}`))
          }
        }

        xhr.onerror = () => {
          reject(new Error('网络错误'))
        }

        xhr.ontimeout = () => {
          reject(new Error('上传超时'))
        }

        xhr.timeout = 30000
        xhr.send(formData)
      })
    },

    // 插入上传的图片
    insertUploadedImage(url, filename) {
      this.editor.chain().focus().setImage({
        src: url,
        alt: filename,
        title: filename
      }).run()
    },

    // 插入上传的视频
    insertUploadedVideo(url, filename, thumbnailUrl = null) {
      // 使用自定义视频节点
      const videoAttrs = {
        src: url,
        controls: true,
        style: 'width: 100%; max-width: 600px;'
      }

      // 如果有封面，添加poster属性
      if (thumbnailUrl) {
        videoAttrs.poster = thumbnailUrl
      }

      this.editor.chain().focus().setVideo(videoAttrs).run()
    },

    // 检查是否为视频文件（通过文件名）
    isVideoFile(filename) {
      if (!filename) return false

      // 从URL中提取文件名（处理阿里云OSS URL参数）
      const cleanFilename = this.extractFilenameFromUrl(filename)
      const videoExtensions = ['mp4', 'webm', 'ogg', 'avi', 'mov', 'wmv', 'flv', 'm4v', '3gp']
      const fileExt = cleanFilename.split('.').pop()?.toLowerCase()

      return videoExtensions.includes(fileExt)
    },

    // 从URL中提取纯文件名（处理OSS参数）
    extractFilenameFromUrl(url) {
      if (!url) return ''

      try {
        // 解析URL，移除查询参数
        const urlObj = new URL(url)
        let pathname = urlObj.pathname

        // 处理URL编码
        pathname = decodeURIComponent(pathname)

        // 提取文件名
        const filename = pathname.split('/').pop() || ''
        console.log('原始URL:', url)
        console.log('路径名:', pathname)
        console.log('提取文件名:', filename)

        return filename
      } catch (error) {
        console.log('URL解析失败，使用降级方法:', error)
        // 如果URL解析失败，直接从字符串中提取
        const questionMarkIndex = url.indexOf('?')
        const cleanUrl = questionMarkIndex > -1 ? url.substring(0, questionMarkIndex) : url
        const filename = cleanUrl.split('/').pop() || ''
        // 处理URL编码的文件名
        return decodeURIComponent(filename)
      }
    },

    // 根据文件扩展名获取视频MIME类型
    getVideoMimeType(filename) {
      // filename已经是提取后的文件名，不需要再次处理
      const fileExt = filename.split('.').pop()?.toLowerCase()
      console.log('文件名:', filename, '扩展名:', fileExt)

      const mimeTypes = {
        'mp4': 'video/mp4',
        'webm': 'video/webm',
        'ogg': 'video/ogg',
        'avi': 'video/x-msvideo',
        'mov': 'video/quicktime',
        'wmv': 'video/x-ms-wmv',
        'flv': 'video/x-flv',
        'm4v': 'video/mp4',
        '3gp': 'video/3gpp'
      }

      return mimeTypes[fileExt] || 'video/mp4'
    },

    // 从URL获取视频MIME类型（处理带参数的URL）
    getVideoMimeTypeFromUrl(url) {
      const filename = this.extractFilenameFromUrl(url)
      console.log('URL:', url)
      console.log('提取的文件名:', filename)
      const mimeType = this.getVideoMimeType(filename)
      console.log('MIME类型:', mimeType)
      return mimeType
    },

    // 插入上传的其他文件
    insertUploadedFile(url, filename, fileType) {
      // 获取文件扩展名（处理OSS URL参数）
      const cleanFilename = this.extractFilenameFromUrl(filename)
      const fileExt = cleanFilename.split('.').pop()?.toLowerCase()

      // 根据文件类型选择emoji图标
      let fileIcon = '📎' // 默认图标
      if (['pdf'].includes(fileExt)) {
        fileIcon = '📄'
      } else if (['doc', 'docx'].includes(fileExt)) {
        fileIcon = '📝'
      } else if (['xls', 'xlsx'].includes(fileExt)) {
        fileIcon = '📊'
      } else if (['ppt', 'pptx'].includes(fileExt)) {
        fileIcon = '📑'
      } else if (['zip', 'rar', '7z'].includes(fileExt)) {
        fileIcon = '📦'
      } else if (['txt', 'md'].includes(fileExt)) {
        fileIcon = '📃'
      }

      // 创建一个文件附件的HTML块
      const fileBlock = `
        <div class="file-attachment-block" contenteditable="false">
          <a href="${url}" target="_blank" download="${filename}">
            <span class="file-icon">${fileIcon}</span>
            <span class="file-name">${filename}</span>
          </a>
        </div>
        <p></p>
      `

      // 插入HTML内容
      this.editor.commands.insertContent(fileBlock)
    },

    // 切换源码显示
    toggleSourceCode() {
      this.showSourceCode = !this.showSourceCode
      if (this.showSourceCode) {
        // 切换到源码模式时，获取当前HTML内容
        this.sourceCodeContent = this.editor.getHTML()
      } else {
        // 切换回富文本模式时，将源码内容设置到编辑器
        this.editor.commands.setContent(this.sourceCodeContent, false)
      }
    },

    // 从源码更新编辑器内容
    updateFromSourceCode() {
      // 防抖处理，避免频繁更新
      clearTimeout(this.sourceCodeUpdateTimer)
      this.sourceCodeUpdateTimer = setTimeout(() => {
        this.$emit('input', this.sourceCodeContent)
      }, 500)
    }
  }
}
</script>

<style lang="scss" scoped>
.tiptap-editor {
  border: 1px solid #d1d5db;
  border-radius: 4px;
  background: white;

  .editor-toolbar {
    padding: 10px;
    border-bottom: 1px solid #e5e7eb;
    background: #f9fafb;

    .el-button {
      &.is-active {
        color: #409eff;
        background: #ecf5ff;
      }
    }
  }

  .editor-content {
    position: relative;
    min-height: 200px;
    max-height: 400px;
    overflow-y: auto;

    ::v-deep .ProseMirror {
      padding: 15px;
      min-height: 200px;
      outline: none;

      p {
        margin: 0 0 10px 0;
      }

      h1, h2, h3 {
        margin: 15px 0 10px 0;
      }

      h1 {
        font-size: 28px;
      }

      h2 {
        font-size: 24px;
      }

      h3 {
        font-size: 20px;
      }

      ul, ol {
        padding-left: 30px;
        margin: 10px 0;
      }

      img {
        max-width: 100%;
        height: auto;
        margin: 10px 0;
      }

      .video-wrapper {
        margin: 10px 0;
        text-align: center;

        video {
          width: 100%;
          max-width: 600px;
          height: auto;
          border: 1px solid #e4e7ed;
          border-radius: 4px;
          background: #000;
        }

        // iframe视频的样式（YouTube等）
        &.embed-video {
          position: relative;
          padding-bottom: 56.25%;
          height: 0;

          iframe {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
          }
        }
      }

      p.is-editor-empty:first-child::before {
        content: attr(data-placeholder);
        float: left;
        color: #adb5bd;
        pointer-events: none;
        height: 0;
      }

      // 文件附件块样式
      .file-attachment-block {
        display: inline-block;
        margin: 5px 0;

        a {
          display: inline-flex;
          align-items: center;
          gap: 8px;
          padding: 8px 16px;
          background: #f0f9ff;
          border: 1px solid #b3d8ff;
          border-radius: 6px;
          color: #409eff;
          text-decoration: none;
          font-size: 14px;
          transition: all 0.2s;

          &:hover {
            background: #409eff;
            color: white;
            border-color: #409eff;
          }

          .file-icon {
            font-size: 16px;
          }

          .file-name {
            max-width: 300px;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
          }
        }
      }
    }

    // 拖拽上传遮罩层
    .drag-upload-overlay {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background: rgba(64, 158, 255, 0.1);
      border: 2px dashed #409eff;
      border-radius: 4px;
      display: flex;
      align-items: center;
      justify-content: center;
      z-index: 10;
    }

    .drag-upload-content {
      text-align: center;
      color: #409eff;

      i {
        font-size: 48px;
        margin-bottom: 10px;
        display: block;
      }

      p {
        margin: 0 0 5px 0;
        font-size: 16px;
        font-weight: 600;
      }

      small {
        font-size: 12px;
        color: #909399;
      }
    }

    // 上传进度
    .upload-progress {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      background: white;
      padding: 20px;
      border-radius: 8px;
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
      min-width: 200px;
      text-align: center;
      z-index: 20;

      span {
        display: block;
        margin-top: 10px;
        font-size: 14px;
        color: #606266;
      }
    }

    // 批量上传进度样式
    .batch-upload-progress {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      background: white;
      padding: 25px;
      border-radius: 8px;
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
      min-width: 300px;
      max-width: 400px;
      text-align: center;
      z-index: 20;

      .progress-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 15px;
        font-size: 14px;
        font-weight: 500;
        color: #303133;

        .failed-count {
          color: #f56c6c;
          font-size: 12px;
        }
      }

      .current-file {
        margin-top: 10px;
        font-size: 12px;
        color: #909399;
        text-align: left;
        word-break: break-all;
        max-height: 40px;
        overflow: hidden;
        text-overflow: ellipsis;
      }
    }

    // 源码编辑器样式
    .source-code-editor {
      padding: 15px;
      min-height: 200px;

      .el-textarea {
        .el-textarea__inner {
          font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
          font-size: 13px;
          line-height: 1.5;
          background: #f8f9fa;
          border: 1px solid #e4e7ed;
          border-radius: 4px;
          resize: vertical;
          min-height: 200px;

          &:focus {
            border-color: #409eff;
            background: #fff;
          }
        }
      }
    }
  }
}
</style>
